package cn.qingyun.gis.modules.sftp.Job;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.qingyun.gis.exception.CommonException;
import cn.qingyun.gis.modules.caronline.service.ICarProofreadService;
import cn.qingyun.gis.modules.express.constant.RedisContant;
import cn.qingyun.gis.modules.express.entity.ExpressRegion;
import cn.qingyun.gis.modules.express.service.IExpressProofreadService;
import cn.qingyun.gis.modules.express.service.IExpressRegionService;
import cn.qingyun.gis.modules.init.system.entity.SysLog;
import cn.qingyun.gis.modules.init.system.mapper.SysLogMapper;
import cn.qingyun.gis.modules.init.utils.CsvTool;
import cn.qingyun.gis.modules.scenes.service.IRegionAddrService;
import cn.qingyun.gis.modules.sftp.config.SftpProperties;
import cn.qingyun.gis.modules.sftp.service.IFileSystemService;
import cn.qingyun.gis.modules.takeaway.service.ITakeawayDataHandleService;
import cn.qingyun.gis.modules.youshang.service.IYsChannelProofreadService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.io.InputStream;
import java.util.List;
import java.util.concurrent.TimeUnit;


/**
 * 定时任务类
 */
@Component
@Async
@Slf4j
public class DataExportExcelJob {
    @Resource
    private IYsChannelProofreadService iYsChannelProofreadService;
    @Resource
    private IFileSystemService iFileSystemService;
    @Resource
    private IExpressRegionService iExpressRegionService;
    @Resource
    private ITakeawayDataHandleService iTakeawayDataHandleService;
    @Resource
    private IExpressProofreadService iExpressProofreadService;

    @Resource
    private ICarProofreadService iCarProofreadService;

    @Resource
    private IRegionAddrService regionAddrService;

    @Resource
    private SysLogMapper sysLogMapper;
    @Resource
    private SftpProperties config;

    @Resource
    private RedissonClient redissonClient;

    @Value("${qingyun.sftp.cachePath:/tmp/}")
    private String cachePath; // 本地缓存路径


    // @Scheduled(cron = "${qingyun.timjob.exportFileJob.time:-}") // 默认定时任务不会触发
    void testFixedDelayString() {
        log.debug("1-定时任务触发时间:" + DateUtil.format(DateUtil.date(), "yyyy/MM/dd HH:mm:ss"));
        String fileName = "ExportYsChannelDetail" + DateUtil.format(DateUtil.date(), "yyyyMMdd") + ".xlsx";

        // 将已勘误增量友商数据从库中导出，进行宿主机本地缓存
        iYsChannelProofreadService.exportYsChannelTotal(cachePath, fileName, "sftp");
        // 将excel文件进行input流转换
        InputStream inputStream = FileUtil.getInputStream(cachePath + fileName);
        // 从本地缓存路径中调取文件，通过SFTP进行上传
        try {
            iFileSystemService.uploadFile("/myg/" + fileName, inputStream); //linux只能支持英文路径 同时需要解决无法上传至根目录下
            inputStream.close();
        } catch (Exception e) {
            log.error("使用SFTP上传云桌面失败！");
            throw new CommonException("使用SFTP上传云桌面失败！");
        }
    }

    // 调用SFTP定时获取最新业务区划数据
    // 默认定时任务不会触发，每日凌晨0点触发
    @Scheduled(cron = "${qingyun.timjob.getRegionJob.time:-}")
    void scheduledGetGrid() {
        RLock rlock = redissonClient.getLock(RedisContant.SCHEDULED_JOB_LOCK);
        log.debug("获取业务区划任务触发时间:" + DateUtil.format(DateUtil.date(), "yyyy/MM/dd HH:mm:ss"));
        SysLog sysLog = new SysLog(); // 创建日志对象
        String fileName = "W08130" + DateUtil.format(DateUtil.yesterday(), "yyyyMMdd") + "000000.csv";

        List<ExpressRegion> data = Lists.newArrayList();
        String message = null; // 日志内容
        long start = System.currentTimeMillis();
        try {
            boolean lockRes = rlock.tryLock(10, TimeUnit.SECONDS);
            if (lockRes) {
                File file = iFileSystemService.downloadFile(config.getRoot() + "/" + fileName, cachePath);
                if (ObjectUtil.isNotEmpty(file)) {
                    log.debug("开始解析...");
                    data = CsvTool.transferFile(file, ExpressRegion.class);
                    log.debug("边界数据已经更新");
                    if(!data.isEmpty()){
                        //更新库-业务区划表
                        iExpressRegionService.remove(new QueryWrapper<>());
                        if(iExpressRegionService.saveBatch(data)){
                            // 若库中数据已经更新，进行84->02
                            iExpressRegionService.wkt84To02();
                        }
                        message = String.format("SFTP获取业务区划%s,更新业务区划表成功", fileName);
                        log.debug("使用SFTP获取最新业务区划数据更新成功");
                        //TODO 更新pg中的region_addr表 还未在生产测试
                        /*regionAddrService.remove(new QueryWrapper<>());
                        log.debug("删除数据成功！");
                        ArrayList<RegionAddr> regionAddrs = Lists.newArrayList();
                        data.forEach(expressRegion->{
                            RegionAddr regionAddr = new RegionAddr();
                            BeanUtils.copyProperties(expressRegion,regionAddr);
                            if (StringUtils.isNotEmpty(expressRegion.getLevel())){
                                regionAddr.setLevel(Integer.valueOf(expressRegion.getLevel()));
                            }
                            regionAddr.setCreateTime(new Date());
                            regionAddr.setUpdateTime(new Date());
                            regionAddrs.add(regionAddr);
                        });
                        if(CollectionUtils.isNotEmpty(regionAddrs)){
                            boolean result = regionAddrService.saveBatch(regionAddrs);
                            if (result){
                                regionAddrService.wkt84To02AndCalcPoint();
                            }
                            log.debug("更新pg表region_addr表完毕！");
                        }*/
                    }
                }
            }
        } catch (Exception e) {
            message = String.format("SFTP获取业务区划%s,更新业务区划表失败", fileName);
            log.error("使用SFTP获取最新业务区划数据失败！");
        } finally {
            rlock.unlock();
            long finish = System.currentTimeMillis();
            sysLog.setLogContent(message);
            sysLog.setCreateTime(DateUtil.date());
            sysLog.setLogType(3); //定时任务日志类型
            sysLog.setCreateBy("system");
            sysLog.setCostTime(finish - start);
            sysLog.setUserid("定时任务");
            sysLogMapper.insert(sysLog);
        }

    }

    // 生产环境每日凌晨0.30点执行 快递 业务区划重新匹配
    @Scheduled(cron = "${qingyun.timjob.matchGridJob.time1:-}")
    void scheduledExpressMatchGrid() {

        log.debug("快递站点自动匹配入格任务触发时间:" + DateUtil.format(DateUtil.date(), "yyyy/MM/dd HH:mm:ss"));
        RLock rlock = redissonClient.getLock(RedisContant.SCHEDULED_JOB_LOCK);
        try {
            boolean lockRes = rlock.tryLock(10, TimeUnit.SECONDS);
            if (lockRes) {
                // 快递站点重新匹配入格
                iExpressProofreadService.matchGrid();
                log.debug("快递站点日常匹配入格成功");
            }
        } catch (Exception e) {
            log.error("快递站点日常匹配入格错误！");
        } finally {
            rlock.unlock();
        }

    }

    // 生产环境每日凌晨1点执行 友商 业务区划重新匹配
    @Scheduled(cron = "${qingyun.timjob.matchGridJob.time2:-}")
    void scheduledYsChannelMatchGrid() {
        log.debug("友商渠道自动匹配入格任务触发时间:" + DateUtil.format(DateUtil.date(), "yyyy/MM/dd HH:mm:ss"));
        RLock rlock = redissonClient.getLock(RedisContant.SCHEDULED_JOB_LOCK);
        try {
            boolean lockRes = rlock.tryLock(10, TimeUnit.SECONDS);
            // 友商站点重新匹配入格
            if (lockRes) {
                iYsChannelProofreadService.matchGrid();
                log.debug("友商渠道日常匹配入格成功");
            }
        } catch (Exception e) {
            log.error("友商渠道日常匹配入格错误！");
        } finally {
            rlock.unlock();
        }

    }

    // 生产环境每日凌晨2点执行 外卖 业务区划重新匹配
    @Scheduled(cron = "${qingyun.timjob.matchGridJob.time3:-}")
    void scheduledTakeawayMatchGrid() {
        log.debug("外卖站点自动匹配入格任务触发时间:" + DateUtil.format(DateUtil.date(), "yyyy/MM/dd HH:mm:ss"));
        RLock rlock = redissonClient.getLock(RedisContant.SCHEDULED_JOB_LOCK);
        try {
            boolean lockRes = rlock.tryLock(5, TimeUnit.SECONDS);
            if (lockRes) {
                // 外卖站点重新匹配入格
                iTakeawayDataHandleService.matchGrid();
                log.debug("外卖站点日常匹配入格成功");
            }

        } catch (Exception e) {
            log.error("外卖站点日常匹配入格错误！");
        } finally {
            rlock.unlock();
        }

    }

    // 生产环境每日凌晨2点10分执行 网约车 业务区划重新匹配
    @Scheduled(cron = "${qingyun.timjob.matchGridJob.time4:-}")
    void scheduledCarMatchGrid() {
        log.debug("网约车站点自动匹配入格任务触发时间:" + DateUtil.format(DateUtil.date(), "yyyy/MM/dd HH:mm:ss"));
        RLock rlock = redissonClient.getLock(RedisContant.SCHEDULED_JOB_LOCK);

        try {
            boolean lockRes = rlock.tryLock(10, TimeUnit.SECONDS);
            if (lockRes) {
                // 网约车站点重新匹配入格
                iCarProofreadService.matchGrid();
                log.debug("网约车站点日常匹配入格成功");
            }
        } catch (Exception e) {
            log.error("网约车站点日常匹配入格错误！");
        } finally {
            rlock.unlock();
        }
    }

    @Scheduled(cron = "${qingyun.timjob.deleteLogJob.time:-}")
    void scheduledLogFormatting(){
        sysLogMapper.delete(null);
    }
}
